#pragma once

namespace Graphics{
	class AnimationSampler{
	public:
		enum AnimationTargetComponent	{	
											ATC_TRANSLATION_X,
											ATC_TRANSLATION_Y,
											ATC_TRANSLATION_Z,
			
											ATC_SCALE_X,
											ATC_SCALE_Y,
											ATC_SCALE_Z,

											ATC_ORIENTATION_X,
											ATC_ORIENTATION_Y,
											ATC_ORIENTATION_Z,
											
											ATC_VISIBILITY,
											ATC_TRANSFORM
										};

		enum AnimationSamplingType		{
											AST_INTERPOLATION,
											AST_INPUT,
											AST_OUTPUT,
											AST_IN_TANGENT,
											AST_OUT_TANGENT
										};

		enum AnimationInterpolationType	{
											AIT_STEP,
											AIT_BEZIER,
											AIT_LINEAR
										};

		AnimationSampler(std::map<AnimationSamplingType,std::vector<float>>& samplerData, std::map<AnimationSamplingType,unsigned int>& samplerStrides, unsigned int targetJoint, AnimationTargetComponent targetComp);

		std::vector<float> sample(float time);
		unsigned int getTargetJoint() { return m_targetJoint; }
		AnimationTargetComponent getTargetComponent() { return m_targetComp; }
	private:
		void interpolateLinear(std::vector<float>& result, float time, int inputId[2]);
		void interpolateBezier(std::vector<float>& result, float time, int inputId[2]);

		float approximateCubicBezierParameter(float atX, float P0_X, float C0_X, float C1_X, float P1_X);
		float clampToZeroOne(float value);

		std::map<AnimationSamplingType,std::vector<float>> m_samplerData;
		std::map<AnimationSamplingType,unsigned int> m_samplerStrides;

		unsigned int m_targetJoint;
		AnimationTargetComponent m_targetComp;
	};

	typedef boost::shared_ptr<AnimationSampler> AnimationSamplerPtr;
}